package com.demo.controller;

import com.demo.config.RabbitMqUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * @author zhiqiang
 */
@RestController
@RequestMapping("/rabbitmq")
@Slf4j
public class RabbitmqController {
    @Autowired
    private AmqpTemplate amqpTemplate;

    /**
     * 发送消息
     * 交换器类型：direct
     */
    @PostMapping("/sendMessage")
    public void sendMessage() {
        // 消息内容
        String message = "你好，我是你爸爸";
        // 交换器名称
        String exchange = "first.direct";
        // 路由地址
        String routing = "direct.routing.1";
        /*
         convert 把消息体和路由键转换成一个完整的消息对象，类型 Message
         send 发送消息结束
         */
        try {
            amqpTemplate.convertAndSend(exchange, routing, message);
            log.info("成功发送消息，信息内容【{}】", message);
        } catch (AmqpException e) {
            log.error("发送消息失败，交换器【{}】，路由地址【{}】", exchange, routing, e);
        }
    }

    /**
     * 主动接收消息，接收完成之后mq会自动删除已被接收的消息
     * 每一次只接受一条消息
     *
     * @return
     */
    @PostMapping("/receiveMessage")
    public Object receiveMessage() {
        // 队列名称
        String queue = "direct.queue.1";
        Object message = null;
        try {
            message = amqpTemplate.receiveAndConvert(queue);
        } catch (AmqpException e) {
            log.error("接收消息失败，消息队列【{}】", queue, e);
        }
        return message;
    }

    /**
     * 发送多条消息，发送的消息在mq中以队列的方式存储，遵守先进先出原则
     * 交换器类型：direct
     */
    @PostMapping("/sendMessages")
    public void sendMessages() {
        String message = "羊";
        String exchange = "first.direct";
        String routing = "direct.routing.1";
        for (int i = 0; i < 6; i++) {
            try {
                amqpTemplate.convertAndSend(exchange, routing, message + i);
                log.info("成功发送消息，信息内容【{}】", message + i);
            } catch (AmqpException e) {
                log.error("发送消息失败，交换器【{}】，路由地址【{}】", exchange, routing, e);
            }
        }
    }

    /**
     *
     * @throws IOException
     * @throws TimeoutException
     */
    @PostMapping("createQueue")
    public void createQueue() throws IOException, TimeoutException {
        // 获取RabbitMQ连接对象
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare("QUEUE_NAME", false, false, false, null);
        String msg="hello";
        /*
        void BasicPublish(string exchange, string routingKey, bool mandatory, IBasicProperties basicProperties, byte[] body);
        void BasicPublish(this IModel model, PublicationAddress addr, IBasicProperties basicProperties, byte[] body);
        void BasicPublish(this IModel model, string exchange, string routingKey, IBasicProperties basicProperties, byte[] body);
        void BasicPublish(this IModel model, string exchange, string routingKey, bool mandatory = false, IBasicProperties basicProperties = null, byte[] body = null);
        exchange:要将消息发送到的Exchange(交换器)
        routingKey:路由Key
        mandatory:如果为true, 消息不能路由到指定的队列时，会触发channel.BasicReturn事件，如果为false，则broker会直接将消息丢弃。
       （channel.BasicReturn += Channel_BasicReturn;）
        basicProperties:其它的一些属性
        body:消息内
         */
        channel.basicPublish("", "QUEUE_NAME", null, msg.getBytes());
        channel.close();
        connection.close();
    }
}
